package beastick.configurator.types;

//Copyright 2008 Tofig Kareemov, estereos@gmail.com
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

import java.util.HashMap;

import beastick.configurator.CConfigurator;
import beastick.utility.CUtilityMethods;

public class CTypedMap extends HashMap
{
  private static final long serialVersionUID = -3721840074124385671L;
  private String  sType                 = "";
  private boolean bChildrenAreMergeable = true;
  private String  sError                = "";
  private HashMap oTypes                = new HashMap();

  public String getType()
  {
    return sType;
  }

  public void setType(String isType)
  {
    sType = isType;
  }

  public boolean getChildrenAreMergeable()
  {
    return bChildrenAreMergeable;
  }

  public void setChildrenAreMergeable(boolean ibChildrenAreMergeable)
  {
    bChildrenAreMergeable = ibChildrenAreMergeable;
  }

  public CTypedMap()
  {
    super();
  }

  public CTypedMap(String isValue, CConfigurator oConfigurator)
  {
    super();
    FillIn(bChildrenAreMergeable, isValue, oConfigurator);
  }

  public CTypedMap(boolean ibChildrenAreMergeable, String isValue,
    CConfigurator oConfigurator)
  {
    super();
    FillIn(ibChildrenAreMergeable, isValue, oConfigurator);
  }

  public void FillIn(boolean ibChildrenAreMergeable, String sParamName,
    CConfigurator oConfigurator)
  {
    String sItemType = "";
    if (!CUtilityMethods.IsValuable(sParamName)
      || !CUtilityMethods.IsValuable(oConfigurator))
    {
      return;
    }
    if (oConfigurator.ParameterExists(sParamName + ".ChildrenAreMergeable"))
    {
      ibChildrenAreMergeable = oConfigurator.GetValueAsBoolean(sParamName
        + ".ChildrenAreMergeable");
    }
    bChildrenAreMergeable = ibChildrenAreMergeable;
    sType = oConfigurator.GetValueAsString(sParamName + ".Type");
    int iSize = oConfigurator.GetValueAsInt(sParamName + ".List");
    try
    {
      if (iSize > 0)
      {
        if (!CUtilityMethods.IsValuable(sType))
        {
          sType = String.class.getName();
        }
        for (int i = 0; i < iSize; ++i)
        {
          String sKey = oConfigurator.GetValueAsString(sParamName + ".List."
            + i + ".Key");
          if (!CUtilityMethods.IsValuable(sKey))
          {
            sKey = sParamName + ".List." + i;
          }
          sItemType = oConfigurator.GetValueAsString(sParamName + ".List." + i
            + ".Type");
          if (!CUtilityMethods.IsValuable(sItemType))
          {
            sItemType = sType;
          }
          Object oValue = null;
          if (oConfigurator.IsTypeConvertible(sItemType))
          {
            if (CTypedMap.class.getName().equals(sItemType))
            {
              Object oFindTypedMapItem = null;
              if (bChildrenAreMergeable)
              {
                oFindTypedMapItem = get(sKey);
              }
              if (oFindTypedMapItem instanceof CTypedMap)
              {
                ((CTypedMap) oFindTypedMapItem).FillIn(bChildrenAreMergeable,
                  sParamName + ".List." + i + ".Value", oConfigurator);
                oValue = (CTypedMap) oFindTypedMapItem;
              }
              else
              {
                oValue = new CTypedMap(sParamName + ".List." + i + ".Value",
                  oConfigurator);
              }
            }
            else
            {
              oValue = oConfigurator.GetValueAsObjectByTypeName(sItemType,
                sParamName + ".List." + i + ".Value");
            }
          }
          else
          {
            oValue = Class.forName(sItemType).newInstance();
            oConfigurator.SetMyInstanceFieldsExplicitly(oValue, sParamName
              + ".List." + i + ".Value");
          }
          put(sKey, oValue);
        }
      }
    }
    catch (Throwable T)
    {
      sError += T.toString();
    }
  }

  public Object put(Object oKey, Object oValue)
  {
    oTypes.put((String) oKey + ":Type", oValue.getClass().getName());
    return super.put(oKey, oValue);
  }

  public String getError()
  {
    String sResult = sError;
    sError = "";
    return sResult;
  }

  public String getItemType(Object oKey)
  {
    return (String) oTypes.get((String) oKey + ":Type");
  }

  public Class getItemTypeClass(Object oKey)
  {
    try
    {
      return Class.forName((String) oTypes.get((String) oKey + ":Type"));
    }
    catch (ClassNotFoundException e)
    {
      sError += e.toString();
      return null;
    }
  }
}